package com.maolong.ackpro.config;


import com.rabbitmq.client.ConnectionFactory;
import lombok.Data;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.annotation.EnableRabbit;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;

@Data
@Configuration
@EnableRabbit
@ConfigurationProperties("spring.rabbitmq")
public class RabbitMqConfig {
    private static final String ACK_BACK_EXCHANGE_NAME = "ack_back_exchange";
    private static final String ACK_BACK_QUEUE_NAME = "ack_back_queue";
    private static final String ACK_QUEUE_NAME = "ack_queue";
    private static final String ACK_EXCHANGE_NAME = "ack_exchange";
    private String host;
    private int port;
    private String username;
    private String password;

    /**
     * 必须配置连接缓冲池
     * @return
     */
    @Bean
    public CachingConnectionFactory cachingConnectionFactory(){
        CachingConnectionFactory factory = new CachingConnectionFactory();
        factory.setHost(host);
        factory.setPassword(password);
        factory.setUsername(username);
        factory.setPort(port);
        /**
         * 方法用于设置确认回调方法，setPublisherConfirmType方法
         * 用于设置发布确认类型为CORRELATED。在sendMessage方法中，
         * 每条消息都会分配一个唯一的关联ID，并通过convertAndSend方法发送。
         */
        factory.setPublisherConfirmType(CachingConnectionFactory.ConfirmType.CORRELATED);
        return factory;
    }

    /**
     * rabbitTemplate的配置
     * @param ackCallBack
     * @param returnCallBack
     * @return
     */
    @Bean
    public RabbitTemplate rabbitTemplate(AckCallBack ackCallBack, ReturnCallBack returnCallBack) {
        RabbitTemplate template = new RabbitTemplate(cachingConnectionFactory());
        template.setConfirmCallback(ackCallBack);
        template.setMandatory(true);//true交换机回退 false 直接丢弃
        template.setReturnsCallback(returnCallBack);
        return template;
    }
    /**
     * 注册队列
     * @return
     */
    @Bean
    public Queue ackQueue() {
        return new Queue(ACK_QUEUE_NAME,true);
    }
    @Bean
    public Queue ackBackQueue() {
        return new Queue(ACK_BACK_QUEUE_NAME,true);
    }

    /**
     * 注册交换机
     * @return
     */
    //声明交换机。并指定备份交换机
    @Bean
    public TopicExchange ackExchange() {
//        HashMap<String, Object> map = new HashMap<>();
//        //绑定了备份交换机
//        map.put("alternate-exchange",ACK_BACK_EXCHANGE_NAME);
//        return new TopicExchange(ACK_EXCHANGE_NAME,true,false,map);
        return ExchangeBuilder
                .topicExchange(ACK_EXCHANGE_NAME)
                .durable(true)
                .withArgument("alternate-exchange",ACK_BACK_EXCHANGE_NAME)
                .build();
    }
    //注意。备份交换机可以是任何类型
    @Bean
    public FanoutExchange ackBackExchange() {
        return new FanoutExchange(ACK_BACK_EXCHANGE_NAME,true,false);
    }

    /**
     * 绑定队列和交换机
     * @return
     */
    @Bean
    public Binding binding() {
        return BindingBuilder
                .bind(ackQueue())
                .to(ackExchange())
                .with("ack.#");
    }
    @Bean
    public Binding bindingBack() {
        return BindingBuilder
                .bind(ackBackQueue())
                .to(ackBackExchange());
    }


}
